﻿using System;
using System.Data.SqlClient;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FluentAssertions;
using Portal.Repository;
using Portal.Model;
using Rhino.Mocks;
using System.Data;

namespace Portal.Repository.Tests.System
{
	[TestClass()]
	public class UserRepositoryTests : BaseTests
	{
		private PortalUnitOfWork _unitOfWork;

		[TestCleanup]
		public void TestCleanup()
		{
			_unitOfWork.Dispose();
		}

		[TestInitialize]
		protected override void InitializeTest()
		{
			_unitOfWork = new PortalUnitOfWork("Server=PortalDatabase;Database=Portal;integrated security=True;");
		}

		#region GetBy
		[TestMethod()]
		public void GetUserBy_UserExists_ReturnsUser()
		{
			var login = Guid.NewGuid().ToString();
			var lastName = "last name";
			var firstName = "first name";

			var user = Mocks.Stub<IUser>();
			user.Expect(x => x.Login).Return(login);
			user.Expect(x => x.Id).Return(123);
			user.FirstName = firstName;
			user.LastName = lastName;

			Mocks.ReplayAll();

			InsertUser(user);

			var repository = GetRepository();
			var result = repository.GetBy(login);

			result.Should().NotBeNull();
		}

		[TestMethod()]
		public void GetUserBy_UserDoesNotExist_ReturnsNull()
		{
			var login = Guid.NewGuid().ToString();
			var repository = GetRepository();
			var result = repository.GetBy(login);

			result.Should().BeNull();
		}

		[TestMethod()]
		public void GetUserBy_LoginIsNull_ReturnsNull()
		{
			var repository = GetRepository();
			var result = repository.GetBy(null);

			result.Should().BeNull();
		}

		#endregion

		#region Insert

		[TestMethod()]
		public void AddOrUpdate_UserIsNull_ReturnsNull()
		{
			var repository = GetRepository();
			var result = repository.AddOrUpdate(null);

			result.Should().BeNull();
		}

		[TestMethod()]
		public void AddOrUpdate_UserExists_UserUpdated()
		{
			var login = Guid.NewGuid().ToString();

			var existing = Mocks.Stub<IUser>();
			existing.Expect(x => x.Login).Return(login);
			existing.Expect(x => x.Id).Return(123);
			existing.LastName = "last name";
			existing.FirstName = "first name";

			var user = Mocks.Stub<IUser>();
			user.Expect(x => x.Login).Return(login);
			user.Expect(x => x.Id).Return(123);
			user.LastName = "last";
			user.FirstName = "first";

			Mocks.ReplayAll();

			InsertUser(existing);

			var repository = GetRepository();
			var result = repository.AddOrUpdate(user);

			result.Should().NotBeNull();
			result.LastName.Should().Be(user.LastName);
			result.FirstName.Should().Be(user.FirstName);
		}

		[TestMethod()]
		public void AddOrUpdate_UserDoesNotExist_UserInserted()
		{
			//var login = "login";

			//var user = Mocks.DynamicMock<IUser>();
			//user.Expect(x => x.Login).Return(login);
			//user.Expect(x => x.Id).Return(123);
			//user.LastName = "last name";
			//user.FirstName = "first name";

			//Mocks.ReplayAll();

			//var repository = GetRepository();
			//var result = repository.AddOrUpdate(user);
			//Assert.IsNotNull(result);
			//Assert.AreEqual(user.LastName, result.LastName);
			//Assert.AreEqual(user.FirstName, result.FirstName);
		}

		#endregion

		private IUserRepository GetRepository()
		{
			return new UserRepository(_unitOfWork);
		}

		private void InsertUser(IUser user)
		{
			using (var command = new SqlCommand())
			{
				command.Connection = _unitOfWork.Connection;
				command.Transaction = _unitOfWork.Transaction;
				command.CommandType = CommandType.Text;
				command.CommandText = "INSERT INTO [dbo].[User] (login,firstname, lastname) VALUES(@login, @firstname, @lastname) ";

				command.Parameters.Add("@login", SqlDbType.VarChar);
				command.Parameters["@login"].Value = user.Login;

				command.Parameters.Add("@firstname", SqlDbType.VarChar);
				command.Parameters["@firstname"].Value = user.FirstName;

				command.Parameters.Add("@lastname", SqlDbType.VarChar);
				command.Parameters["@lastname"].Value = user.LastName;

				command.ExecuteScalar();
			}
		}
	}
}